package com.tozed.android.launcher.simpleui;

import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;

import com.tozed.android.launcher.DeferredHandler;
import com.tozed.android.launcher.LauncherApplication;
import com.tozed.android.launcher.simpleui.SimpleLauncherModel.Callbacks;

public class SimpleLauncherModel extends BroadcastReceiver
{
	static final boolean DEBUG_LOADERS = true;
	static final String TAG = "SimpleLauncher.Model";
	static final String ACTION_MMS_RECEIVED = "android.provider.Telephony.WAP_PUSH_RECEIVED";
	
	static final Uri CONTENT_URI;
	private static final int ITEMS_CHUNK = 6; // 每次往工作区批量绑定的图标数
	private static boolean needSimpleLauncherRefresh;
	
	static ArrayList<SimpleApplicationInfo> sDownloadApps;	// 下载APP
	static ArrayList<SimpleItemInfo> sFavoriteItems = 
			new ArrayList<SimpleItemInfo>(); 				// 桌面展示的APP
	static ArrayList<SimpleLauncherAppWidgetInfo> sFavoriteWidgets = 
			new ArrayList<SimpleLauncherAppWidgetInfo>(); 	// 桌面展示的Widget
	static ArrayList<SimpleItemInfo> sFolders = new ArrayList<SimpleItemInfo> (); 	   // 文件夹
	//static ArrayList<IconMatchInfo> sIconMatchInfos;
	
	static final HashMap<Long, SimpleItemInfo> sItemsIdMap; // id和对应的应用信息缓存
	static ArrayList<SimpleApplicationInfo> sOtherApps = new ArrayList<SimpleApplicationInfo>();// 其它APP
	
	private static final Handler sWorker;
	private static final HandlerThread sWorkerThread;
	private SimpleAllAppsList mAllAppsList;		// 所有应用
	private LauncherApplication mApp;
	private WeakReference<Callbacks> mCallbacks;
	private HashMap<ComponentName, String> mFavoriteDeskApps = new HashMap<ComponentName, String>();
	private WeakReference<FolderCallbacks> mFolderCallbacks;
	private boolean mFolderLoaded;
	private DeferredHandler mHandler = new DeferredHandler();	// 队列Handler
	private SimpleIconCache mIconCache;
	private HashMap<Object, CharSequence> mLabelCache;
	private LoaderTask mLoaderTask;
	private final Object mLock = new Object();
	private boolean mWorkspaceLoaded;
	
	protected int mPreviousConfigMcc;
	
	static
	{
		sDownloadApps = new ArrayList();
		sItemsIdMap = new HashMap();
		//sIconMatchInfos = new ArrayList();
		CONTENT_URI = Uri.parse("content://com.tozed.android.launcher.settings/favorites?notify=true");
		needSimpleLauncherRefresh = false;
		sWorkerThread = new HandlerThread("simple-launcher-loader");
		sWorkerThread.start();
		sWorker = new Handler(sWorkerThread.getLooper());
	}
	
	// 主要加载接口回调定义
	public static abstract interface Callbacks{
		public abstract void startBinding();
		public abstract void bindItems(List<SimpleItemInfo> shortcuts, int start, int end);
		public abstract void bindFolders(List<SimpleItemInfo> folders);
		public abstract void finishBindingItems();
		public abstract void bindWidgets(List<SimpleLauncherAppWidgetInfo> appWidgetInfos);
		public abstract void bindAppsAdded(ArrayList<SimpleApplicationInfo> apps, boolean permanentAdd);
		public abstract void bindAppsRemoved(ArrayList<SimpleApplicationInfo> apps, boolean flag);
		public abstract void bindAppsUpdated(ArrayList<SimpleApplicationInfo> apps);
		public abstract void bindNeedAddedItemsAndSave();
        public void bindUnreadNumberUpdated(int type, int number);
		public boolean isAllAppsVisible();
	}
	
	// 文件夹内APP加载接口回调定义
	public static abstract interface FolderCallbacks{
		public abstract void bindAppsChanged();
		public abstract void reloadApps();
	}
	
	public SimpleLauncherModel(LauncherApplication app, SimpleIconCache cache)
	{
		mApp = app;
		mIconCache = cache;
		mAllAppsList = new SimpleAllAppsList(mIconCache);
		
		final Resources res = app.getResources();
        Configuration config = res.getConfiguration();
        mPreviousConfigMcc = config.mcc;
	}
	
	 /**
     * 设置实现了Callbacks接口的SimpleUILauncher对应的Activity
     */
    public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            mCallbacks = new WeakReference<Callbacks>(callbacks);
        }
    }
    
    // 设置实现了FolderCallbacks接口对应的Activity
    public void initializeFolder(FolderCallbacks folderCallbacks)
    {
      synchronized (mLock){
        mFolderCallbacks = new WeakReference(folderCallbacks);
      }
    }
    
    /************************************数据库操作相关****************************************/
    // 添加或更新app数据信息
	public static void addOrUpdtateItemInDatabase(Context context, SimpleApplicationInfo appInfo)
	{
		// 在缓存中找不到该id则在数据库中新增app信息
		if (!sItemsIdMap.containsKey(Long.valueOf(appInfo.id)))
			addItemToDatabase(context, appInfo, true);
		else
			updateItemInDatabaseHelper(context, new ContentValues(), appInfo);
	}
    
    // 添加app项到数据中
    public static void addItemToDatabase(Context context, SimpleApplicationInfo item, final boolean notify)
    {
    	 final ContentValues values = new ContentValues();
         final ContentResolver cr = context.getContentResolver();
         
         item.onAddToDatabase(values);
         sFavoriteItems.add(item); // 用于桌面展示的app信息缓存
         
         LauncherApplication app = (LauncherApplication)context.getApplicationContext();
         
         item.id = app.getLauncherProvider().generateSimpleNewId();
         values.put(SimpleLauncherSettings.SimpleFavorites._ID, Long.valueOf(item.id));
         values.put(SimpleLauncherSettings.SimpleFavorites.TITLE, item.title.toString());
         
		 if (item.iconPackage != null)
			 values.put(SimpleLauncherSettings.SimpleFavorites.ICON_PACKAGE, item.iconPackage);
		 if (item.iconResource != null)
			 values.put(SimpleLauncherSettings.SimpleFavorites.ICON_RESOURCE, item.iconResource);
         
         Runnable r = new Runnable() {
             public void run() {
                 cr.insert(notify ? SimpleLauncherSettings.SimpleFavorites.CONTENT_URI :
                	 SimpleLauncherSettings.SimpleFavorites.CONTENT_URI_NO_NOTIFICATION, values);
             }
         };
         
         if (sWorkerThread.getThreadId() == Process.myTid()) {
             r.run(); // 已在本线程中
         } else {
             sWorker.post(r); // post到sWorkerThread线程等待处理
         } 
    }
    
    // 更新app项数据
    public static void updateItemInDatabaseHelper(Context context, final ContentValues values, final SimpleApplicationInfo item)
    {
        final ContentResolver cr = context.getContentResolver();
        final Uri uriToUpdate = SimpleLauncherSettings.SimpleFavorites.getContentUri(item.id, false);
        
        sWorker.post(new Runnable() {
                public void run() {
                	cr.update(uriToUpdate, values, null, null);
                }
            });
    }
    
    // 更新原始数项数据
    public static void updateItemInDatabaseHelper(Context context, final ContentValues values, SimpleItemInfo item)
    {
    	final ContentResolver cr = context.getContentResolver();
        final Uri uriToUpdate = SimpleLauncherSettings.SimpleFavorites.getContentUri(item.id, false);
        
        sWorker.post(new Runnable() {
                public void run() {
                	cr.update(uriToUpdate, values, null, null);
                }
            });
    }

    // 添加删除的app项(表为删除表)
    static void addItemToDeleteDateBase(Context context, SimpleApplicationInfo appInfo){
    	// TODO: 暂时不需要
    }
    
    // 根据包名删除数据库中收藏的项
    public void deleteItemInSimpleDataBasedByPackageName(String strPkgName)
    {
    	// TODO: implement
    	// 读出intent字段值,再根据Intent比较包名是否一致再删除之
    	final ContentResolver cr = mApp.getContentResolver();
    	Uri uri = SimpleLauncherSettings.SimpleFavorites.CONTENT_URI;
    	
    	String selection = SimpleLauncherSettings.SimpleFavorites.CONTAINER + " =? and " + 
    			SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE + " =?";
    	String[] selectionArgs = new String[] {String.valueOf(SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP), 
    			String.valueOf(SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_APPLICATION)};
    	
    	Cursor c = cr.query(uri, null, selection, selectionArgs, null);
    	if (c != null)
    	{
    		try{
	            final int idIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites._ID);
	            final int intentIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.INTENT);
	            
	    		while (c.moveToNext()){
	    			int id = c.getInt(idIndex);
	    			String strIntent = c.getString(intentIndex);
	    			// 对比是否有些包名,如果有删除之
	    			if (strIntent.contains(strPkgName)){
	    				deleteItemByIdFromSimpleDataBase(mApp, id);
	    				break;
	    			}
	    		}
    		} finally {
            	c.close();
			}
    	}
    }
    
    // 从删除表里删除app数据项
    public static void deleteItemFromDeleteDatabase(Context context, SimpleApplicationInfo appInfo){
    	// TODO: 暂时不需要
    }
    
    // 从数据库中删除APP
    public static void deleteAppFromDatabase(Context context, final SimpleApplicationInfo item, boolean addToDeletedTable)
    {
    	final ContentResolver cr = context.getContentResolver();
        final Uri uriToDelete = SimpleLauncherSettings.SimpleFavorites.getContentUri(item.id, false);
        
        sWorker.post(new Runnable() {
                public void run() {
                	sItemsIdMap.remove(Long.valueOf(item.id));
                    cr.delete(uriToDelete, null, null);
                }
            });
        
        if (addToDeletedTable)
            addItemToDeleteDateBase(context, item);
    }
    
    public static void deleteItemByIdFromSimpleDataBase(Context context, final int itemId)
    {
    	final ContentResolver cr = context.getContentResolver();
        final Uri uriToDelete = SimpleLauncherSettings.SimpleFavorites.getContentUri(itemId, false);
        
        sWorker.post(new Runnable() {
                public void run() {
                	sItemsIdMap.remove(Long.valueOf(itemId));
                    cr.delete(uriToDelete, null, null);
                }
            });
    }
    
    public static void deleteItemInfoFromDatabase(Context context, final SimpleItemInfo item)
    {
    	final ContentResolver cr = context.getContentResolver();
        final Uri uriToDelete = SimpleLauncherSettings.SimpleFavorites.getContentUri(item.id, false);
        
        sWorker.post(new Runnable() {
                public void run() {
                	sItemsIdMap.remove(Long.valueOf(item.id));
                    cr.delete(uriToDelete, null, null);
                }
            });
    }
    
    // 删除主Launcher表中的?
    public static void deleteItemFromLauncherDatabase(Context context, SimpleApplicationInfo item)
    {
    	final ContentResolver cr = context.getContentResolver();
        Intent intent = new Intent("android.intent.action.MAIN", null);
        intent.addCategory("android.intent.category.LAUNCHER");
        intent.setComponent(item.componentName);
        intent.setFlags(270532608);
        
        final String strIntentDescription = intent.toUri(0);
        sWorker.post(new Runnable() {
            public void run() {
            	String selection = SimpleLauncherSettings.SimpleFavorites.INTENT + "=?";
                cr.delete(SimpleLauncherModel.CONTENT_URI, selection, new String[] { strIntentDescription });
            }
        });
    }
    
    // 从sdcard读数据并删除原有的固定项
    public boolean getDataInDb(Context context, SimpleApplicationInfo appInfo)
    {
    	/*
    	boolean ret = false;
    	
    	ContentResolver cr = context.getContentResolver();
        Uri uri = SimpleLauncherSettings.SimpleFavorites.CONTENT_URI_SD_CARD;
        String[] selectionArgs = new String[]{appInfo.intent.toUri(0)};
        
        Cursor c = cr.query(uri, null, "intent=?", selectionArgs, null);
        if (c != null)
        {
        	try {
        		while(c.moveToNext()){
	        		if (c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites.DISPLAY_MODE)) == 1){
	        			appInfo.id = c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites._ID));
	        			appInfo.container = c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites.CONTAINER));
	        			appInfo.screen = c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites.SCREEN));
	        			appInfo.cellX = c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites.CELLX));
	        			appInfo.cellY = c.getInt(c.getColumnIndex(SimpleLauncherSettings.SimpleFavorites.CELLY));
	        			appInfo.isFixedPosition = true;
	        			deleteItemFromDeleteDatabase(mApp, appInfo);
	        			ret = true;
	        			break;
	        		}
        		}
        	}catch (Exception e) {
        		c.close();
        	}finally {
        		c.close();
        	}
        }
        
        if (c != null)
        	c.close();
        
        return ret;
        */
    	
    	return true; // 暂时不需要删除表
    }
    
    // 根据项信息从数据库中获得图标字节序并转成位图
	Bitmap getIconFromCursor(Cursor c, int iconIndex, Context context, SimpleItemInfo itemInfo)
	{
		try{
			if (itemInfo.itemType == SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_SHORTCUT){
				byte[] bytes = c.getBlob(iconIndex);
				Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
				return bmp;
			}
		} catch (Exception e){
			
		}
		
		return null;
	}
    /************************************数据库操作end*****************************************/
	
	
	/************************************缓存等数据操作相关****************************************/
	// 获得SimpleUILauncher对象
	public SimpleUILauncher getLauncher()
	{
		if (mCallbacks != null){
	      Callbacks callbacks = (Callbacks)this.mCallbacks.get();
	      if (callbacks != null && (callbacks instanceof SimpleUILauncher))
	        return (SimpleUILauncher)callbacks;
	    }
		
	    return null;
	}
	
	public Handler getWorker(){
		return sWorker;
	}
	
    // 添加已下载app信息
    public static void addDownloadApp(SimpleApplicationInfo appInfo)
    {
    	//debugLog("addDownloadApp pkgName=" + appInfo.getPkgName());
		if ((sDownloadApps != null) && (sDownloadApps.size() >= 0)){
			sDownloadApps.add(appInfo);
			AddApplicationViewCache.getInstance().updateAllAppsView(appInfo, false);
		}
    }
	
	// 添加其它(所有)APPs
	public static void addOthersApp(SimpleApplicationInfo appInfo)
	{
		//debugLog("addOthersApp pkgName=" + appInfo.getPkgName());
		if ((sOtherApps != null) && (sOtherApps.size() >= 0)){
	      sOtherApps.add(appInfo);
	      AddApplicationViewCache.getInstance().updateAllAppsView(appInfo, false);
	    }
	}
	
	// 排列文件夹图标
	public static void arrangeFolderIcons(List<SimpleApplicationInfo> appList)
	{
		int count = appList.size();
		int cellX, cellY, screen;
		
		for (int i = 0; i < count; i++){
			SimpleItemInfo info = (SimpleItemInfo)appList.get(i);
			
			// 主要为了应用于每个CellLayout为16个图标的视图中
			cellX = i%4;
			cellY = (i/4)%4;
			screen = i/16; // 当前在哪一屏
			info.setShortcutPosition(cellX, cellY, screen);
		}
	}
	
	static ComponentName getComponentNameFromResolveInfo(ResolveInfo resolveInfo)
	{
		if (resolveInfo.activityInfo != null)
			return new ComponentName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
		else
			return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
	}
	
	// 获得最近运行的app信息
	public static SimpleApplicationInfo getRecentShortcutInfo(ResolveInfo resolveInfo)
	{
		ComponentName component = getComponentNameFromResolveInfo(resolveInfo);
		
		int otherAppsSize = sOtherApps.size();
		for (int i = 0; i < otherAppsSize; i++)
		{
			SimpleApplicationInfo app = (SimpleApplicationInfo)sOtherApps.get(i);
			if (component.equals(app.getComponentName()))
				return app;
		}
		
		int downLoadAppsSize = sDownloadApps.size();
		for (int j = 0; j < downLoadAppsSize; j++)
		{
			SimpleApplicationInfo app = (SimpleApplicationInfo)sDownloadApps.get(j);
			if (component.equals(app.getComponentName()))
				return app;
		}
		
		return null;
	}
	
	// 获得应用项信息
	private SimpleItemInfo getShortcutInfo(Cursor c, Context context, int iconIndex)
	{
		SimpleItemInfo itemInfo = new SimpleItemInfo();
		itemInfo.itemType = SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_SHORTCUT;
		
		itemInfo.setIcon(getIconFromCursor(c, iconIndex, context, itemInfo));
		return itemInfo;
	}
	
	// 从下载APP缓存中删除一个app
	public static void removeDownloadApp(SimpleApplicationInfo appInfo)
	{
		//debugLog("removeDownloadApp: pkgName=" + appInfo.getPkgName());
		if ((sDownloadApps != null) && (sDownloadApps.size() > 0)){
			sDownloadApps.remove(appInfo);
			AddApplicationViewCache.getInstance().updateAllAppsView(appInfo, true);
		}
	}

	// 从其它(所有)APP缓存中删除一个app
	public static void removeOtherApp(SimpleApplicationInfo appInfo)
	{
		//debugLog("removeOtherApp: pkgName=" + appInfo.getPkgName());
		if ((sOtherApps != null) && (sOtherApps.size() > 0)){
			sOtherApps.remove(appInfo);
			AddApplicationViewCache.getInstance().updateAllAppsView(appInfo, true);
		}
	}
	
	public SimpleApplicationInfo infoFromAppExternalIntent(Context context, Intent intent, SimpleItemInfo itemInfo)
	{
		Intent externalIntent = (Intent)intent.getParcelableExtra("android.intent.extra.shortcut.INTENT");
	    Log.i(TAG, "SimpleLauncherMode infoFromAppExternalIntent intent = " + externalIntent);
	    
	    if (externalIntent == null){
	    	Log.w(TAG, "SimpleLauncherModeCan't construct ShorcutInfo with null intent");
	    	return null;
	    }
	    
	    int count = sOtherApps.size();
	    for (int i = 0; i < count; i++)
	    {
	      SimpleApplicationInfo appInfo = (SimpleApplicationInfo)sOtherApps.get(i);
	      if (appInfo.intent.getComponent().equals(externalIntent.getComponent())){
	    	  Log.i(TAG, "SimpleLauncherModesOtherApps simpleApplicationInfo.id = " + appInfo.id);
		      appInfo.intent = externalIntent;
		      return appInfo;
	      }
	    }
	    
	    for (int i = 0; i < sDownloadApps.size(); i++)
	    {
	      SimpleApplicationInfo appInfo = (SimpleApplicationInfo)sDownloadApps.get(i);
	      if (appInfo.intent.getComponent().equals(externalIntent.getComponent())){
	    	  appInfo.intent = externalIntent;
		      Log.i(TAG, "SimpleLauncherModesDownloadApps simpleApplicationInfo.id = " + appInfo.id);
		      return appInfo;
	      }
	    }
	    
	    return null;
	}
	
	// 快捷方式Intent
	public SimpleApplicationInfo infoFromShortcutIntent(Context context, Intent intent, SimpleItemInfo itemInfo)
	{
		int itemType = SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_SHORTCUT; // shortcut
		
	    Intent shortcutIntent = (Intent)intent.getParcelableExtra("android.intent.extra.shortcut.INTENT");
	    String strTitle = intent.getStringExtra("android.intent.extra.shortcut.NAME");
	    Parcelable parcelable = intent.getParcelableExtra("android.intent.extra.shortcut.ICON");
	    
		if (shortcutIntent == null || itemInfo == null)
		{
			StringBuilder sb = new StringBuilder();
			if (shortcutIntent == null)
			{
				sb.append("SimpleLauncherMode Can't construct ShorcutInfo with intent == null");
				if (itemInfo != null){
					itemType = SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_APPLICATION; // application
				} else{
					sb.append(",originItem == null");
				}
			}

			Log.e(TAG, sb.toString());
			return null;
		}
	    
	    Bitmap bmpIcon = null;
	    if (parcelable != null && (parcelable instanceof Bitmap)){
	    	  bmpIcon = (Bitmap)parcelable;
	    }
	    
	    SimpleApplicationInfo app = new SimpleApplicationInfo();
	    app.itemType = itemType;
	    app.container = SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP;
	    app.screen = itemInfo.screen;
	    app.cellX = itemInfo.cellX;
	    app.cellY = itemInfo.cellY;
	    app.spanX = itemInfo.spanX;
	    app.spanY = itemInfo.spanY;
	    app.setIcon(bmpIcon);
	    app.title = strTitle;
	    app.intent = shortcutIntent;
	    
	    return app;
	}
	
	// 从文件夹删除项
	public ArrayList<SimpleApplicationInfo> removeItemFromFolders(Context paramContext, String pkgName)
	{
		ArrayList<SimpleApplicationInfo> appResutList = null;
		
		ArrayList<SimpleApplicationInfo> allAppList = new ArrayList<SimpleApplicationInfo>();
		allAppList.addAll(sDownloadApps);
		allAppList.addAll(sOtherApps);
		
	    if (allAppList.size() > 0)
	    {
	      // 根据包名找出需删除的项
	      appResutList = new ArrayList<SimpleApplicationInfo>();
	      Iterator<SimpleApplicationInfo> it = allAppList.iterator();
	      while (it.hasNext())
	      {
	        SimpleApplicationInfo item = (SimpleApplicationInfo)it.next();
	        ComponentName componentName = item.componentName;
	        if (componentName != null && pkgName.equals(componentName.getClassName()))
	        	appResutList.add(item);
	      }
	      
	      // 从下其它和下载APP中删除缓存
	      Iterator<SimpleApplicationInfo> it2 = appResutList.iterator();
	      while (it2.hasNext())
	      {
	        SimpleApplicationInfo appRemove = (SimpleApplicationInfo)it2.next();
	        removeOtherApp(appRemove);
	        removeDownloadApp(appRemove);
	      }
	    }
	    
	    return appResutList;
	}
	
	public void removeItemfromFolder(SimpleApplicationInfo item, boolean removeFromDownload)
	{
	    if (item != null)
	    {
	      if (removeFromDownload)
	        removeFromDownload(item);
	      else
	    	removeFromOther(item); 
	    }
	}
	
	// 根据安装时间来排序文件夹里的应用
	public static void sortAndArrangeFolderApps(ArrayList<SimpleApplicationInfo> appInfoList)
	{
		Collections.sort(appInfoList, new ShortcutNameComparator());
		arrangeFolderIcons(appInfoList);
	}

	private void sortFolderApps()
	{
		sortAndArrangeFolderApps(sDownloadApps);
		sortAndArrangeFolderApps(sOtherApps);
	}
	
	// 重新添加新APP到文件夹缓存中并刷新
	public void addItemIntoFolder(SimpleApplicationInfo appInfo, boolean isDownloadApp)
	{
		if (appInfo != null)
	    {
		  appInfo.container = -1;
		  
	      if (!isDownloadApp)
	    	  addOthersApp(appInfo);
	      else
	    	  addDownloadApp(appInfo);
	      
	      reloadFolders();
	    }
	}
	
	public void refreshApp()
	{
		if (mCallbacks != null)
		{
			final Callbacks callbacks = (Callbacks) mCallbacks.get();
			if (callbacks == null){
				Log.w(TAG,"SimpleLauncherModeNobody to tell about the new app.  Launcher is probably loading.");
				return;
			}

			mHandler.post(new Runnable()
			{
				public void run(){
					if (mFolderCallbacks != null){
						FolderCallbacks folderCallbacks = mFolderCallbacks.get();
						if (folderCallbacks != null){
							folderCallbacks.bindAppsChanged();
							
							// TODO: mFolderLoaded = true?
							// SimpleLauncherModel.access$1102(true);
						}
					}
					callbacks.bindFolders(SimpleLauncherModel.sFolders);
				}
			});
		}
	}
	
	public void reloadFolders()
	{
		if (this.mCallbacks != null);
		
		if (mCallbacks != null)
		{
			final Callbacks callbacks = (Callbacks) mCallbacks.get();
			if (callbacks == null){
				Log.w(TAG,"SimpleLauncherModeNobody to tell about the new app.  Launcher is probably loading.");
				return;
			}
			
			mHandler.post(new Runnable()
			{
				public void run(){
					 sortFolderApps();
					 if (mFolderCallbacks != null)
					 {
						 FolderCallbacks folderCallbacks = mFolderCallbacks.get();
							if (folderCallbacks != null){
								folderCallbacks.bindAppsChanged();
								
								mFolderLoaded = true;
							}
					 }
					 
					 callbacks.bindFolders(SimpleLauncherModel.sFolders);
				}
			});
		}
	}
	
	// 清除所有缓存项
	public void clearItems()
	{
		Runnable r = new Runnable() {
            public void run() {
            	//SimpleLauncherModel.sIconMatchInfos.clear();
                SimpleLauncherModel.sFavoriteItems.clear();
                SimpleLauncherModel.sFavoriteWidgets.clear();
                SimpleLauncherModel.sFolders.clear();
                SimpleLauncherModel.sOtherApps.clear();
                SimpleLauncherModel.sDownloadApps.clear();
                SimpleLauncherModel.sItemsIdMap.clear();
                if (mAllAppsList != null)
                   mAllAppsList.clear();
                if (mLabelCache != null)
                   mLabelCache.clear();
                mFavoriteDeskApps.clear();
            }
        };
        
        if (sWorkerThread.getThreadId() == Process.myTid()) {
            r.run();
        } else {
            sWorker.post(r);
        } 
	}
	
	public void removeFromDownload(SimpleApplicationInfo appInfo){
		removeDownloadApp(appInfo);
		reloadFolders();
	}

	public void removeFromOther(SimpleApplicationInfo appInfo){
		removeOtherApp(appInfo);
		reloadFolders();
	}
	
	// TODO: 待实现
	boolean findAppWidgetProviderInfoWithComponent(List<AppWidgetProviderInfo> widgetProviderList, ComponentName componentName)
	{
		Iterator<AppWidgetProviderInfo> it = widgetProviderList.iterator();
		while (it.hasNext()){
			if (((AppWidgetProviderInfo) it.next()).provider.equals(componentName))
				return true;
		}
		
		return false;
	}

	// 暂时用不上
	public void findIconMatch(SimpleApplicationInfo appInfo)
	{
		
	}
	/************************************缓存等数据操作End****************************************/
	
	// 广播接收应用添加，删除，更新事件
	@Override
	public void onReceive(Context context, Intent intent)
	{
		debugLog("onReceive intent=" + intent);
	    final String action = intent.getAction();
	    
	    if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
            || Intent.ACTION_PACKAGE_REMOVED.equals(action)
            || Intent.ACTION_PACKAGE_ADDED.equals(action)) 
        {
	    	final String packageName = intent.getData().getSchemeSpecificPart();
        	// 是否要替换包
        	final boolean isReplacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
        	
        	int op = PackageUpdatedTask.OP_NONE;
        	
        	if (packageName == null || packageName.length() == 0) {
                // 无效的Intent
                return;
            }
        	
        	if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                op = PackageUpdatedTask.OP_UPDATE;
            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
                if (!isReplacing) {
                    op = PackageUpdatedTask.OP_REMOVE;
                }
                // 更新一个包的时候，先发PACKAGE_REMOVED，再发PACKAGE_ADDED广播，所以下面还要判断一下
            } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
                if (!isReplacing) {
                    op = PackageUpdatedTask.OP_ADD;
                } else {
                    op = PackageUpdatedTask.OP_UPDATE;
                }
            }
        	
        	// 丢入任务队列中
            if (op != PackageUpdatedTask.OP_NONE) {
                enqueuePackageUpdated(new PackageUpdatedTask(op, new String[]{ packageName }));
            }
        }else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)){
        	// 重新加载可用的应用,如SD卡恢复
        	String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
        	enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
        	// 加载
        	//startLoaderFromBackground();
        	forceReload();
        }else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
        	String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
        	enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UNAVAILABLE, packages));
        }else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
        	// 语言改变强制重新加载
        	forceReload();
        }else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
        	// mcc改变强制重新加载
			Configuration currentConfig = context.getResources().getConfiguration();
			if (mPreviousConfigMcc != currentConfig.mcc){
				 Log.d(TAG, "Reload apps on config change. curr_mcc:"
	                       + currentConfig.mcc + " prevmcc:" + mPreviousConfigMcc);
				 
				forceReload();
			}
			
			mPreviousConfigMcc = currentConfig.mcc;
        }else if (ACTION_MMS_RECEIVED.equals(action)){
        	enqueueUnreadNumberUpdated(new UnreadNumberUpdatedTask(UnreadNumberUpdatedTask.TYPE_MMS));
        }
	}
	
	// 电话未接数、短信未读数更新
	public void updateUnReadCount(int type){
		enqueueUnreadNumberUpdated(new UnreadNumberUpdatedTask(type));
	}
	
	public boolean getFolderLoaded()
	{
		return this.mFolderLoaded;
	}
	
	public void destroyFolderCallbacks()
	{
		synchronized (mLock){
		  mFolderCallbacks = null;
		}
	}

	// 强制重新加载
	//private void forceReload()
	public void forceReload()
	{
		synchronized (mLock){
			stopLoaderLocked();
			mWorkspaceLoaded = false;
			mFolderLoaded = false;
			mIconCache.flush();
			startLoader(mApp, false);
		}
	}

	// 如果已有任务，先停止。如果SimpleLauncher正在启动返回true
    private boolean stopLoaderLocked() {
        boolean isLaunching = false;
        LoaderTask oldTask = mLoaderTask;
        if (oldTask != null) {
            if (oldTask.isLaunching()) {
                isLaunching = true;
            }
            oldTask.stopLocked();
        }
        return isLaunching;
    }
	
	// 开始加载
	public void startLoader(Context context, boolean isLaunching) 
	{
        synchronized (mLock) 
        {
            debugLog("startLoader isLaunching=" + isLaunching);
            // 如果知道没事可做，不要刻意启动线程
            if (mCallbacks != null && mCallbacks.get() != null) {
                isLaunching = isLaunching || stopLoaderLocked();
                mLoaderTask = new LoaderTask(context, isLaunching);
                sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                sWorker.post(mLoaderTask);
            }
        }
    }

    public void stopLoader() 
    {
        synchronized (mLock) {
            if (mLoaderTask != null) {
                mLoaderTask.stopLocked();
            }
        }
    }
	
	/*
	 * 主要提供线程加载app,widget信息的类
	 */
	private class LoaderTask implements Runnable
	{
		private Context mContext;
		private boolean mIsLaunching;
		private boolean mStopped;
		private boolean mLoadAndBindStepFinished;
		
		public LoaderTask(Context context, boolean isLaunching)
		{
			mContext = context;
			mIsLaunching = isLaunching;
			
			// SimpleLauncherModel.access$002(SimpleLauncherModel.this, new HashMap());
		}
		
		public boolean isLaunching(){
			return mIsLaunching;
		}
		
		private void waitForIdle() 
		{
            synchronized (LoaderTask.this) {
                final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;

                mHandler.postIdle(new Runnable() {
                        public void run() {
                            synchronized (LoaderTask.this) {
                                mLoadAndBindStepFinished = true;
                                debugLog("done with previous binding step");
                                
                                LoaderTask.this.notify();
                            }
                        }
                    });
                
                // 一直等待第一步加载完后，直到触发notify后再往后第二步加载操作
                while (!mStopped && !mLoadAndBindStepFinished) {
                    try {
                        this.wait();
                    } catch (InterruptedException ex) {
                    	//
                    }
                }
                
                // 第一步加载花费的时间
                long timepass = SystemClock.uptimeMillis() - workspaceWaitTime;
                debugLog("waited " + timepass + "ms for previous step to finish binding");
            }
        }

		@Override
		public void run()
		{
			final Callbacks cbk = mCallbacks.get();
			final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
			
			// 标签块用法
			keep_running: 
			{
				synchronized (mLock){
					android.os.Process.setThreadPriority(mIsLaunching
							? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
				}
				
				if (loadWorkspaceFirst){
					debugLog("step 1: loading workspace");
					loadAndBindWorkspace();
				}else{
					debugLog("step 1: special: loading all apps");
					// 加载所有app， 已分到其它app和下载app中
					//loadAndBindAllApps();
				}
				
				if (mStopped){
					break keep_running;
				}
				
				synchronized (mLock){
					if(mIsLaunching) 
					   android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
				}
				
				// 等第一步加载完后, 再加载第二步
				waitForIdle();
				
				if (loadWorkspaceFirst){
					debugLog("step 2: loading all apps");
					// 绑定所有app， 已分到其它app和下载app中
					// loadAndBindAllApps();
				}else{
					debugLog("step 2: special: loading workspace");
					loadAndBindWorkspace();
				}
			}
			
			// 清除引用,否则会一占用直到所有的callback runnable运行完
            mContext = null;

            synchronized (mLock) {
                if (mLoaderTask == this) mLoaderTask = null;
            }
            
            // 加载完成后 ,触发gc垃圾回收,让系统可能会去回收对象(由虚拟机决定)
            // gc作用只是提醒虚拟机：程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行，
            // 而且具体什么时候进行是取决于具体的虚拟机的，不同的虚拟机有不同的对策
            if (mStopped){
                mHandler.post(new Runnable() {
                        public void run() {
                            System.gc();
                        }
                    });
            } else {
                mHandler.postIdle(new Runnable() {
                        public void run() {
                            System.gc();
                        }
                    });
            }
		}
		
		// 加载主页工作区(包含3个SimpleCellLayout)
		private void loadAndBindWorkspace()
		{
			debugLog("loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
			
			if (true || !mWorkspaceLoaded)
			{
				loadWorkspace();
				if(mStopped)
					return;
				
				mWorkspaceLoaded = true;
			}
			
			bindWorkspace();
			
			// 新增操作: 加载和绑定文件夹,更新所有APP视图数据
			loadAndBindFolder();
	        AddApplicationViewCache.getInstance().updateAllAppsViewData();
		}
		
		// 主要用于从数据库加载用于桌面显示的APP和widget及文件夹
		private void loadWorkspace()
		{
			// TODO: 注释部分后期是否需要
			//mApp.getLauncherProvider().getDatabaseHelper().checkSimpleTable();
			
			// 加载默认资源
			mApp.getLauncherProvider().loadDefaultSimpleFavoritesIfNecessary(0);
			
		    mFavoriteDeskApps.clear();
		    sFavoriteItems.clear();
		    sFavoriteWidgets.clear();
		    sFolders.clear();
		    mAllAppsList.clear();
		    //sIconMatchInfos.clear();
		    
		    // 加载桌面应用展示
		    getFavoriteAppItem(mContext);
		    // 加载widget小插件
		    getAppWidgetItems(mContext);
		    // 应用背景色匹配
		    loadIconMatchDb(mContext);
		}
		
		// 从数据库加载桌面APP, workspace里调用,把之前在Loadworkspace里做的移到这里
		void getFavoriteAppItem(Context context)
		{
	        final ContentResolver cr = context.getContentResolver();
	        final PackageManager pm = context.getPackageManager();
	        final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
	        final boolean isSafeMode = pm.isSafeMode(); // 设备是否已进入安全模式
	        
	        sOtherApps.clear();
	        sDownloadApps.clear();
	        sFavoriteItems.clear();
	        
		     // 查询数据库, container为-100(桌面), spanX横向跨度为1 则为app或者快捷方式
			String selection = SimpleLauncherSettings.SimpleFavorites.CONTAINER + "=? and " +
					SimpleLauncherSettings.SimpleFavorites.SPANX + "=?";
			String[] selectionArgs = new String[] {
					String.valueOf(SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP),"1"};
			
	        final Cursor c = cr.query(SimpleLauncherSettings.SimpleFavorites.CONTENT_URI, null, 
	        		selection, selectionArgs, null);
        
	        try{
	        	final int idIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites._ID);
	            final int intentIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.INTENT);
	            final int titleIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.TITLE);
	            final int containerIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CONTAINER);
	            final int itemTypeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE);
	            final int iconTypeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_TYPE);
	            final int iconIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON);
	            final int uriIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.URI); 
	            final int displayModeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.DISPLAY_MODE);
	            final int iconPackageIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_PACKAGE);
	            final int iconResourceIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_RESOURCE);
	            final int appWidgetIdIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.APPWIDGET_ID);
	            
	            final int screenIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SCREEN);
	            final int cellXIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CELLX);
	            final int cellYIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CELLY);
	            final int spanXIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SPANX);
	            final int spanYIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SPANY);
	            
	            SimpleApplicationInfo info;
	            
                int container,screen;
                long id;
                String intentDescription;
                int cellX, cellY, spanX, spanY;
                String strIconResource, strIconPackge, strTitle;
                Intent intent;
                int displayMode; // 用于判断是否是不能删除的应用快捷方式
                boolean fixedPosition;
                
                while (!mStopped && c.moveToNext())
				{
	            	try
					{
	            		int itemType = c.getInt(itemTypeIndex);
	            		id = c.getLong(idIndex);
	            		intentDescription = c.getString(intentIndex);
	            		strIconResource = c.getString(iconResourceIndex);
	            		strIconPackge = c.getString(iconPackageIndex);
	            		strTitle = c.getString(titleIndex);
						cellX = c.getInt(cellXIndex);
						cellY = c.getInt(cellYIndex);
						spanX = c.getInt(spanXIndex);
						spanY = c.getInt(spanYIndex);
						screen = c.getInt(screenIndex);
						displayMode = c.getInt(displayModeIndex);
						
						if (displayMode == 1)
							fixedPosition = true;
						else
							fixedPosition = false;
						
	            		switch (itemType)
						{
	            			// 在桌面的APP信息
							case SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_APPLICATION:
							{
								intentDescription = c.getString(intentIndex);
								try{
									intent = Intent.parseUri(intentDescription, 0);
								} catch (URISyntaxException e){
									continue;
								}
								
								final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
								SimpleApplicationInfo app = new SimpleApplicationInfo(pm, 
										resolveInfo, mIconCache, mLabelCache);
								app.id = id;
								app.iconResource = strIconResource;
								app.iconPackage = strIconPackge;
								app.itemType = itemType;
								app.screen = screen;
								app.isFixedPosition = fixedPosition;
								app.cellX = cellX;
								app.cellY = cellY;
								app.intent = intent;
								app.container = SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP;
								if (strIconResource != null)
									app.isPresetApp = true;
								else
									app.isPresetApp = false;
								
								sFavoriteItems.add(app);
								mFavoriteDeskApps.put(intent.getComponent(), intent.getPackage());
								sItemsIdMap.put(Long.valueOf(app.id), app);
								mAllAppsList.data.add(app);
							}
							break;
							
							// 在桌面的快捷方式
							case SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_SHORTCUT:
							{
								intentDescription = c.getString(intentIndex);
								try{
									intent = Intent.parseUri(intentDescription, 0);
								} catch (URISyntaxException e){
									continue;
								}
								
								SimpleItemInfo shortCutApp = getShortcutInfo(c, context, iconIndex);
								shortCutApp.id = id;
								shortCutApp.iconPackage = strIconPackge;
								shortCutApp.iconResource = strIconResource;
								shortCutApp.title = strTitle;
								shortCutApp.itemType = itemType;
								shortCutApp.screen = screen;
								shortCutApp.isFixedPosition = fixedPosition;
								shortCutApp.cellX = cellX;
								shortCutApp.cellY = cellY;
								shortCutApp.intent = intent;
								shortCutApp.container = SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP;
						        sItemsIdMap.put(Long.valueOf(shortCutApp.id), shortCutApp);
						        sFavoriteItems.add(shortCutApp);
							}
							break;
								
							// 在文件夹中的快捷方式
							case SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_FOLDER:
							{
								 SimpleItemInfo item = new SimpleItemInfo();
								 item.id = id;
								 item.iconPackage = strIconPackge;
								 item.title = strTitle;
								 item.itemType = itemType;
								 item.screen = screen;
								 item.isFixedPosition = fixedPosition;
								 item.cellX = cellX;
								 item.cellY = cellY;
								 item.container = SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP;
							     sItemsIdMap.put(Long.valueOf(item.id), item);
							     sFavoriteItems.add(item);
							     sFolders.add(item);
							}
							break;
							
						}	
					}catch (Exception e) {
						Log.w(TAG, "Desktop app/shortcut items loading interrupted:", e);
					}
				}
	        }finally{
	        	c.close();
	        }
	        
		}
		
		// 从数据库加载widget项, 加载workspace里调用,把之前在Loadworkspace里做的移到这里
		void getAppWidgetItems(Context context)
		{
			final ContentResolver cr = context.getContentResolver();
			final PackageManager manager = context.getPackageManager();
            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
            final boolean isSafeMode = manager.isSafeMode(); // 设备是否已进入安全模式
            
            final ArrayList<Long> itemsToRemoveWidget = new ArrayList<Long>();
			
			// 查询数据库
			String selection = SimpleLauncherSettings.SimpleFavorites.CONTAINER + "=? and " +
					SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE + "=?";
			String[] selectionArgs = new String[] {
					String.valueOf(SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP),
					String.valueOf(SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE_APPWIDGET)};
			
	        final Cursor c = cr.query(SimpleLauncherSettings.SimpleFavorites.CONTENT_URI, null, 
	        		selection, selectionArgs, null);
	        
	        try{
	        	final int idIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites._ID);
	            final int intentIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.INTENT);
	            final int titleIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.TITLE);
	            final int containerIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CONTAINER);
	            final int itemTypeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ITEM_TYPE);
	            final int iconTypeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_TYPE);
	            final int iconIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON);
	            final int uriIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.URI); 
	            final int displayModeIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.DISPLAY_MODE);
	            final int iconPackageIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_PACKAGE);
	            final int iconResourceIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.ICON_RESOURCE);
	            final int appWidgetIdIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.APPWIDGET_ID);
	            
	            final int screenIndex = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SCREEN);
	            final int cellXIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CELLX);
	            final int cellYIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.CELLY);
	            final int spanXIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SPANX);
	            final int spanYIndex  = c.getColumnIndexOrThrow(SimpleLauncherSettings.SimpleFavorites.SPANY);
	            
	            SimpleLauncherAppWidgetInfo appWidgetInfo;
	            int container,screen;
                long id;
                int cellX, cellY, spanX, spanY;
                String intentDescription;
                Intent intent;
	            
	            while (!mStopped && c.moveToNext())
				{
	            	try
					{
		            	int appWidgetId = c.getInt(appWidgetIdIndex);
						id = c.getLong(idIndex);
						cellX = c.getInt(cellXIndex);
						cellY = c.getInt(cellYIndex);
						spanX = c.getInt(spanXIndex);
						spanY = c.getInt(spanYIndex);
						screen = c.getInt(screenIndex);
						
						intentDescription = c.getString(intentIndex);
						try{
							intent = Intent.parseUri(intentDescription, 0);
						} catch (URISyntaxException e){
							Log.e(TAG, "app widget parse intent error.");
							continue;
						}
						
						final AppWidgetProviderInfo provider = appWidgetManager.getAppWidgetInfo(appWidgetId);
						if (!isSafeMode && (provider == null || provider.provider == null
								|| provider.provider.getPackageName() == null)){
							Log.e(TAG, "Deleting widget that isn't installed anymore: id="
	                                + id + " appWidgetId=" + appWidgetId);
							itemsToRemoveWidget.add(id);
						} else{
							// widget绑定过后再绑定会出错
							appWidgetInfo = new SimpleLauncherAppWidgetInfo(appWidgetId);
							appWidgetInfo.id = id;
							// cellX,cellY,SpanX,SpanY
							appWidgetInfo.cellX = cellX;
							appWidgetInfo.cellY = cellY;
							appWidgetInfo.spanX = spanX;
							appWidgetInfo.spanY = spanY;
							appWidgetInfo.screen = screen;
							appWidgetInfo.intent = intent;
							container = c.getInt(containerIndex);
							if(container != SimpleLauncherSettings.SimpleFavorites.CONTAINER_DESKTOP){
								Log.e(TAG, "Widget found where container " + "!= CONTAINER_DESKTOP -- ignoring!");
	                            continue;
							}
							appWidgetInfo.container = c.getInt(containerIndex);
							
							// 检测桌面在指定位置是否已有该项目
							// checkItemPlacement
							
							sFavoriteWidgets.add(appWidgetInfo);
						}
					}catch (Exception e) {
						Log.w(TAG, "Desktop widget items loading interrupted:", e);
					}
				}
	        }finally{
	        	c.close();
	        }
	        
	     	// itemsToRemove 数据库有些项错误的项，删除这些项
            if (itemsToRemoveWidget.size() > 0){
            	// 防止多次acquire provider,用于频繁访问同一个Provider以减少CPU消耗
				ContentProviderClient client = cr.acquireContentProviderClient(
						SimpleLauncherSettings.SimpleFavorites.CONTENT_URI);
				for (long id : itemsToRemoveWidget)
				{
					try{
						// 删除时不通知监控者
						debugLog("removed widget id = " + id);
						client.delete(SimpleLauncherSettings.SimpleFavorites.getContentUri(id, false),null, null);
					}catch (RemoteException e) {
						Log.w(TAG, "could not remove widget id = " + id);
					}
				}
				//client.release();
			} 
		}
		
		// 将Widget和Folders添加到桌面工作区
		private void bindWorkspace()
		{
			final long t = SystemClock.uptimeMillis();
            
            final Callbacks oldCallbacks = mCallbacks.get();
            if (oldCallbacks == null) {
                // launcher已意外退出
                Log.w(TAG, "LoaderTask running with no launcher");
                return;
            }
            
            int count;
            
            // 告诉SimpleUILauncher开始绑定
            mHandler.post(new Runnable(){
				public void run(){
					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
					if (callbacks != null){
						callbacks.startBinding();
					}
				}
			});
            
            // 绑定widget回调,让SimpleUILauncher作一些UI相关Action
            debugLog("Going to bind Widgets size=" + SimpleLauncherModel.sFavoriteWidgets.size());
            if (SimpleLauncherModel.sFavoriteWidgets.size() > 0)
            {
            	mHandler.post(new Runnable(){
    				public void run(){
    					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
    					if (callbacks != null){
    						debugLog("start bindWidgets...");
    						callbacks.bindWidgets(SimpleLauncherModel.sFavoriteWidgets);
    					}
    				}
    			});
            }
            
            // 绑定桌面app回调,让SimpleUILauncher作一些UI相关Action
            count = SimpleLauncherModel.sFavoriteItems.size();
            debugLog("Going to bindItems, count=" + count);
            
            for (int i=0; i<count; i += ITEMS_CHUNK)
			{
            	final int start = i;
            	final int chunkSize = (i+ITEMS_CHUNK <= count) ? ITEMS_CHUNK : (count-i);
            	 mHandler.post(new Runnable(){
     				public void run(){
     					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
     					if (callbacks != null){
     						debugLog("start bindItems...");
     						callbacks.bindItems(SimpleLauncherModel.sFavoriteItems, start, start+chunkSize);
     					}
     				}
     			});
			}
            
            // 等待队列空闲
            mHandler.post(new Runnable(){
				public void run(){
					debugLog("Going to start binding need added soon.");
				}
			});
            
            // 绑定其它
            mHandler.post(new Runnable(){
				public void run(){
					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
					if (callbacks != null){
						callbacks.bindNeedAddedItemsAndSave();
					}
				}
			});
            
            /* 放到bindFolder中
            // 告诉SimpleUILauncher绑定结束
            mHandler.post(new Runnable(){
				public void run(){
					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
					if (callbacks != null){
						callbacks.finishBindingItems();
					}
				}
			});
			*/
            
            // 计算绑定花的时间(入队列最后一件事)
            mHandler.post(new Runnable() {
                public void run() {
                    debugLog("bound workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
                }
            });
		}
		
		// 加载文件夹
		private void loadAndBindFolder()
	    {
			debugLog("step 2: loadAndBindFolder loading other apps and download apps, mFolderLoaded=" + mFolderLoaded);
			
			if (!mFolderLoaded)
			{
				loadFolder();
				if(mStopped)
					return;
				
				mFolderLoaded = true;
			}
			
			bindFolder();
			finishBindFolders();
	    }
		
		private void loadFolder()
		{
			PackageManager pm = mContext.getPackageManager();
			Intent intent = new Intent(Intent.ACTION_MAIN, null);
			intent.addCategory(Intent.CATEGORY_LAUNCHER);
			
			List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(intent, 0);
			if ((resolveInfoList != null) && (resolveInfoList.size() > 0))
				filterDeskApps(resolveInfoList);
			
			Callbacks callbacks = null;
			if (mCallbacks != null)
				callbacks = mCallbacks.get();
			
			if (callbacks == null){
				Log.w(TAG, "SimpleLauncherModeNobody to tell about the new app.  Launcher is probably loading.");
				return;
			}
			
			// 更新Max id?
			LauncherApplication app = (LauncherApplication)((SimpleUILauncher)callbacks).getApplicationContext();
			app.getLauncherProvider().updateMaxIdSimple();
			
			// 根据主题来判断
			//if (app.getResources().getIdentifier("androidhwext:style/Theme.Wallpaper.NoTitleBar", null, null) != 0){
			//	makeItemInfoForNormalHome();
			//}
			
			sortAndArrangeFolderApps(SimpleLauncherModel.sOtherApps);
			sortAndArrangeFolderApps(SimpleLauncherModel.sDownloadApps);
		}
		
		// 绑定文件夹
		private void bindFolder(){
			final Callbacks oldCallbacks = mCallbacks.get();
            if (oldCallbacks == null) {
                // launcher已意外退出
                Log.w(TAG, "LoaderTask running with no launcher");
                return;
            }
	            
			mHandler.post(new Runnable(){
				public void run(){
					if (mFolderCallbacks != null){
						FolderCallbacks folderCallbacks = mFolderCallbacks.get();
						if (folderCallbacks != null){
							folderCallbacks.bindAppsChanged();
							mFolderLoaded = true;
						}
					}
					
					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
					if (callbacks != null){
						callbacks.bindFolders(sFolders);
					}
				}
			});
			
			// 初始化更新电话未、短信未读、Email未读数
			loadAndBindUnreadNumber();
			
			// 告诉SimpleUILauncher绑定结束
            mHandler.post(new Runnable(){
				public void run(){
					final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
					if (callbacks != null){
						callbacks.finishBindingItems();
					}
				}
			});
		}
		
		private void finishBindFolders(){
			
	    }
		
		private void loadAndBindUnreadNumber()
		{
			updateUnReadCount(UnreadNumberUpdatedTask.TYPE_PHONE);
			updateUnReadCount(UnreadNumberUpdatedTask.TYPE_MMS);
		}
		
		// 根据xml隐藏文件和桌面收藏的来过滤用于显示所有app列表中的APP
		private void makeItemInfoForNormalHome()
		{
			PackageManager pm = mContext.getPackageManager();
			Iterator<ResolveInfo> it = pm.queryIntentActivities(
					new Intent("com.tozed.android.launcher.action.ChangeToNormal",null), 0).iterator();
			
			while (it.hasNext())
			{
				ResolveInfo resolveInfo = (ResolveInfo)it.next();
				ComponentName componentName = new ComponentName(
						resolveInfo.activityInfo.applicationInfo.packageName,
						resolveInfo.activityInfo.name);
				
				if ((mFavoriteDeskApps.containsKey(componentName))
					|| (HiddenIconsManager.getInstance().isHiddenIcon(componentName))){
					it.remove();
					continue;
				}
				
				SimpleApplicationInfo item = new SimpleApplicationInfo(pm, resolveInfo, mIconCache, mLabelCache);
				mAllAppsList.data.add(item);
				sOtherApps.add(item);
			}
		}

		// 过滤可以有启动属性(android.intent.category.LAUNCHER)的APP
		public void filterDeskApps(List<ResolveInfo> resolveInfoList)
		{
			PackageManager pm = mContext.getPackageManager();
			
			for (ResolveInfo info : resolveInfoList)
			{
				if (info != null && info.activityInfo != null && info.activityInfo.applicationInfo != null)
				{
					ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
					// 如果桌面已放置了或者想隐藏的APP就不放到其它App文件夹中了
					if (mFavoriteDeskApps.containsKey(component) || HiddenIconsManager.getInstance().isHiddenIcon(component)){
						continue;
					}
					
					SimpleApplicationInfo app = new SimpleApplicationInfo(pm, info, mIconCache, mLabelCache);
					mAllAppsList.data.add(app); // 所有APP缓存列表
					if (app.isBelongToDownloadFolder(pm)){
						sDownloadApps.add(app);	// 下载APP缓存列表
					}else{
						sOtherApps.add(app);	// 其它APP缓存列表
					}
				}
			}
			
			debugLog("after filterDeskApps, " + "AllData.size=" + mAllAppsList.data.size()
					+ ",sDApps.size=" + sDownloadApps.size() + ",sOApps.size=" + sOtherApps.size());
		}
		
		public void loadIconMatchDb(Context context){
			// 界面色块颜色与和intent对应图标
		}
		
		public void stopLocked()
		{
			synchronized (LoaderTask.this){
				mStopped = true;
				this.notify();
			}
		}
		
		/**
		 * 获取callbacks对象 ,如果已经停止,或者launcher对象在某种程度上已被垃圾收集,返回null
		 * 如果Callbacks对象不一样也返回null
		 */
        Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
            synchronized (mLock) {
                if (mStopped) {
                    return null;
                }
                
                // Callbacks在SimpleUILauncher中实现, 
                // Callbacks对象保存在弱引用中
                if (mCallbacks == null) {
                    return null;
                }

                final Callbacks callbacks = mCallbacks.get();
                if (callbacks != oldCallbacks) {
                    return null;
                }
                if (callbacks == null) {
                    Log.w(TAG, "no mCallbacks");
                    return null;
                }

                return callbacks;
            }
        }
	}
	
	void enqueuePackageUpdated(PackageUpdatedTask task){
	    sWorker.post(task);
	}

	private class PackageUpdatedTask implements Runnable
    {
		public static final int OP_NONE = 0;
		public static final int OP_ADD = 1;
		public static final int OP_UPDATE = 2;
		public static final int OP_REMOVE = 3; 		// uninstlled
		public static final int OP_UNAVAILABLE = 4; // external media unmounted
		public static final int OP_AVAILABLE = 5;
	
		int mOption;
		String[] mPackages;

	    public PackageUpdatedTask(int op, String[] packages)
	    {
	      mOption = op;
          mPackages = packages;
	    }
	    
		@Override
		public void run()
		{
			final Context context = mApp;
			final String[] packages = mPackages;
			final int count = packages.length;
			
			switch (mOption)
			{
			case OP_ADD:
				for(int i=0; i<count; i++){
					debugLog("mAllAppsList.addPackage " + packages[i]);
					mAllAppsList.addPackage(context, packages[i]);
				}
				break;
				
			case OP_AVAILABLE:
				
				break;
			
			case OP_UPDATE:
				for(int i=0; i<count; i++){
					debugLog("mAllAppsList.updatePackage " + packages[i]);
					mAllAppsList.updatePackage(context, packages[i]);
				}
				break;
				
			case OP_REMOVE:
			case OP_UNAVAILABLE:
				for(int i=0; i<count; i++){
					debugLog("mAllAppsList.removePackage " + packages[i]);
					mAllAppsList.removePackage(packages[i]);
					
					// 从数据库中删除收藏项
					deleteItemInSimpleDataBasedByPackageName(packages[i]);
				}
				break;
			} 
			
			// 数据处理完成，通知Launcher更新UI
            ArrayList<SimpleApplicationInfo> added = null;
            ArrayList<SimpleApplicationInfo> removed = null;
            ArrayList<SimpleApplicationInfo> modified = null;

            if (mAllAppsList.added.size() > 0) {
                added = mAllAppsList.added;
                mAllAppsList.added = new ArrayList<SimpleApplicationInfo>();
            }
            if (mAllAppsList.removed.size() > 0) {
                removed = mAllAppsList.removed;
                mAllAppsList.removed = new ArrayList<SimpleApplicationInfo>();
                for (SimpleApplicationInfo info: removed) {
                    mIconCache.remove(info.intent.getComponent());
                }
            }
            if (mAllAppsList.modified.size() > 0) {
                modified = mAllAppsList.modified;
                mAllAppsList.modified = new ArrayList<SimpleApplicationInfo>();
            }

            final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
            if (callbacks == null) {
                Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");
                return;
            }
            
            // 新应用
            if (added != null) {
                final ArrayList<SimpleApplicationInfo> addedFinal = added;
                mHandler.post(new Runnable() {
                    public void run() {
                        if (callbacks == mCallbacks.get()) {
                            //callbacks.bindAppsAdded(addedFinal);
                        	callbacks.bindAppsAdded(addedFinal, false);
                        }
                    }
                });
            }
            
            // 应用修改
            if (modified != null) {
                final ArrayList<SimpleApplicationInfo> modifiedFinal = modified;
                mHandler.post(new Runnable() {
                    public void run() {
                        if (callbacks == mCallbacks.get()) {
                            callbacks.bindAppsUpdated(modifiedFinal);
                        }
                    }
                });
            }
            
            //  应用被删除
            if (removed != null) {
                final boolean permanent = mOption != OP_UNAVAILABLE;
                final ArrayList<SimpleApplicationInfo> removedFinal = removed;
                mHandler.post(new Runnable() {
                    public void run() {
                        if (callbacks == mCallbacks.get()) {
                            callbacks.bindAppsRemoved(removedFinal, permanent);
                        }
                    }
                });
            }
		}
    }
	
	public static class ShortcutNameComparator implements Comparator<SimpleApplicationInfo>, Serializable
	{
		public int compare(SimpleApplicationInfo appInfo1, SimpleApplicationInfo appInfo2)
		{
			if (appInfo1.firstInstallTime > appInfo2.firstInstallTime)
				return 1;
			else if (appInfo1.firstInstallTime < appInfo2.firstInstallTime)
				return -1;
			else 
				return 0;
		}
	}
	
	void enqueueUnreadNumberUpdated(UnreadNumberUpdatedTask task) {
    	Log.d(TAG, "enqueueBadgeNumberUpdated");
        sWorker.post(task);
    }
	
    /**
     * 更新电话、短信、Email未接数
     */
    private class UnreadNumberUpdatedTask implements Runnable
    {
    	private int mType;
    	private int mNumber;
    	
    	public static final int TYPE_PHONE = 0;
        public static final int TYPE_MMS = 1;
        public static final int TYPE_EMAIL = 2;
    	
    	public UnreadNumberUpdatedTask(int type){
    		mType = type;
    	}
    	
		public void run()
		{
			switch (mType){
				case TYPE_PHONE:
					mNumber = SimpleUtilities.getMissedCallCount(mApp);
					break;
					
				case TYPE_MMS:
					mNumber = SimpleUtilities.getUnreadMsgCount(mApp);
					break;
					
				case TYPE_EMAIL:
					break;
					
				default:
					return;
			}
			
			// 更新UI
			final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
	        if (callbacks == null) {
	            Log.w(TAG, "SimpleLauncher is probably loading.");
	            return;
	        }
	        
	        final int typeUpated = mType;
	        final int numberUpdated = mNumber;
	        mHandler.post(new Runnable() {
	            public void run() {
	                if (callbacks == mCallbacks.get()) {
	                    callbacks.bindUnreadNumberUpdated(typeUpated, numberUpdated);
	                }
	            }
	        });
		}
    }
	
	public static void debugLog(String str){
		if (DEBUG_LOADERS){
			Log.d(TAG, str);
		}
	}
}
